<?php

namespace addons\thirdwork\library;

use fast\Http;
use think\Cache;
use think\Session;

/**
 * 飞书
 */
class Feishu
{
    const GET_TMP_AUTH_CODE_URL         = 'https://open.feishu.cn/open-apis/authen/v1/index';
    const GET_USER_INFO_BYCODE_URL      = 'https://open.feishu.cn/open-apis/authen/v1/access_token';
    const GET_USER_URL                  = 'https://open.feishu.cn/open-apis/authen/v1/user_info';
    const GET_MEMBER_INFO_URL           = 'https://open.feishu.cn/open-apis/contact/v1/user/batch_get';

    const GET_ACCESS_TOKEN_URL          = 'https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal/';
    const GET_TENANT_ACCESS_TOKEN_URL   = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/';
    const GET_DEPARTMENT_LIST_URL       = 'https://open.feishu.cn/open-apis/contact/v1/department/simple/list';
    const GET_DEPARTMENT_MEMBER_URL     = 'https://open.feishu.cn/open-apis/contact/v1/department/user/list';
    const GET_DEPARTMENT_USER_LIST_URL  = 'https://open.feishu.cn/open-apis/contact/v1/department/user/detail/list';

    /**
     * 配置信息
     * @var array
     */
    private $config = [];

    public function __construct($options = [])
    {
        if ($config = get_addon_config('thirdwork')['feishu']) {
            $this->config = array_merge($this->config, $config);
        }
        $this->config = array_merge($this->config, is_array($options) ? $options : []);
    }

    /**
     * 获取authorize_url
     */
    public function getAuthorizeUrl()
    {
        $state = md5(uniqid(rand(), true));
        Session::set('state', $state);
        $queryarr = array(
            'app_id'        => $this->config['app_id'],
            'redirect_uri'  => $this->config['callback'],
            'state'         => $state,
        );
        request()->isMobile() && $queryarr['display'] = 'mobile';
        $url = self::GET_TMP_AUTH_CODE_URL . '?' . http_build_query($queryarr) . '#feishu_redirect';
        return $url;
    }

    /**
     * 获取用户信息
     * @param array $params
     * @return array
     */
    public function getUserInfo($params = [])
    {
        $params = $params ? $params : request()->get();
        if ((isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) {
            //用code换open_id、user_access_token、refresh_token等登录用户身份
            $queryarr = [
                'app_access_token'  => $this->getAccessToken(),
                'grant_type'        => 'authorization_code',
                'code'              => $params['code'],
            ];
            $options = array(CURLOPT_HTTPHEADER => ['Content-Type:application/json']);
            $ret = Http::post(self::GET_USER_INFO_BYCODE_URL, json_encode($queryarr), $options);
            $ret = (array) json_decode($ret, true);

            // 到这里，可以鉴别是否企业成员
            if (!isset($ret['data']) || $ret['code']) {
                return ['errmsg' => '你不是该企业的成员'];
            }
            $user_access_token = $ret['data']['access_token'];
            $openid = $ret['data']['open_id'];
            // 用user_access_token获取用户信息
            $options = array(CURLOPT_HTTPHEADER => [
                'Content-Type:application/json',
                'Authorization:Bearer '.$user_access_token
            ]);
            $ret = Http::get(self::GET_USER_URL,null,$options);
            $ret = (array) json_decode($ret, true);
            if (!isset($ret['data']) || $ret['code']) {
                return ['errmsg' => $ret['msg']];
            }
            // 用tenant_access_token和open_id获取成员在通讯录中的信息
            $options = array(CURLOPT_HTTPHEADER => [
                'Content-Type:application/json',
                'Authorization:Bearer '.$this->getTenantAccessToken()
            ]);
            $queryarr = [
                'open_ids'  => $openid
            ];
            $ret = Http::get(self::GET_MEMBER_INFO_URL,$queryarr,$options);
            $ret = (array) json_decode($ret, true);
            if (!$ret || $ret['code']) {
                return ['errmsg' => '获取成员详情失败'];
            }
            $userinfo = $ret ? $ret['data']['user_infos'][0] : [];
            $userinfo['userid'] = $userinfo['employee_id'];
            $userinfo['nickname'] = isset($userinfo['name']) ? $userinfo['name'] : '';
            $userinfo['avatar'] = isset($userinfo['avatar_url']) ? $userinfo['avatar_url'] : '';

            $data = [
                'access_token'  => '',
                'refresh_token' => '',
                'expires_in'    => 0,
                'openid'        => $openid,
                'userinfo'      => $userinfo
            ];
            return $data;
        }
        return ['errmsg' => '第三方平台授权失败'];
    }
    /**
     * 获取tenant_access_token
     * @return string
     */
    public function getTenantAccessToken()
    {
        $cache = Cache::get('feishu_tenant_access_token');
        if ($cache) {
            if (isset($cache['tenant_access_token']) && time() < $cache['expire_time']) {
                return $cache['tenant_access_token'];
            }
        }
        $options = array(CURLOPT_HTTPHEADER => ['Content-Type:application/json']);
        $queryarr = [
            'app_id'     => $this->config['app_id'],
            'app_secret' => $this->config['app_secret'],
        ];
        $response = Http::post(self::GET_TENANT_ACCESS_TOKEN_URL, json_encode($queryarr), $options);
        $response = (array) json_decode($response, true);

        if ($response && !$response['code']) {
            Cache::tag('thirdwork')->set('feishu_tenant_access_token', [
                'tenant_access_token'  => $response['tenant_access_token'],
                'expire_time'   => time() + 7200
            ]);
            return $response['tenant_access_token'];
        }
        return '';
    }
    
    /**
     * 获取access_token
     * @return string
     */
    public function getAccessToken()
    {
        $cache = Cache::get('feishu_access_token');
        if ($cache) {
            if (isset($cache['access_token']) && time() < $cache['expire_time']) {
                return $cache['access_token'];
            }
        }
        $options = array(CURLOPT_HTTPHEADER => ['Content-Type:application/json']);
        $queryarr = [
            'app_id'     => $this->config['app_id'],
            'app_secret' => $this->config['app_secret'],
        ];
        $response = Http::post(self::GET_ACCESS_TOKEN_URL, json_encode($queryarr), $options);
        $response = (array) json_decode($response, true);

        if (!$response['code']) {
            Cache::tag('thirdwork')->set('feishu_access_token', [
                'access_token'  => $response['app_access_token'],
                'expire_time'   => time() + 7200
            ]);
            return $response['app_access_token'];
        }
        return '';
    }
    /**
     * 获取部门列表
     * @return array
     */
    public function getDepartmentList()
    {
        $queryarr = array(
            'department_id' => 0,
            'offset'        => 0,
            'page_size'     => 100, //一次最多可获取100个部门
            'fetch_child'   => true
        );
        $options = array(CURLOPT_HTTPHEADER => [
            'Content-Type:application/json',
            'Authorization:Bearer '.$this->getTenantAccessToken()
        ]);
        
        $response = Http::get(self::GET_DEPARTMENT_LIST_URL, $queryarr, $options);
        $response = (array) json_decode($response, true);
        if (!$response['code'] && isset($response['data'])) {
            $data = [];
            if (!isset($response['data']['department_infos'])) {
                return ['code' => 0, 'msg' => '请前往飞书添加部门', 'data' => $response];
            }
            foreach ($response['data']['department_infos'] as $v) {
                $data[] = array('id' => $v['id'], 'parent' => $v['parent_id'], 'text' => $v['name'], 'icon' => 'fa fa-folder-o', 'state' => ['opened' => false, 'selected' => false]);
            }
            // 飞书不支持获取根部门详情，手动插入。
            $data[] = array('id' => 0, 'parent' => '#', 'text' => '组织架构', 'icon' => 'fa fa-folder-o', 'state' => ['opened' => true, 'selected' => true]);
            return ['code' => 1, 'data' => $data];
        }
        return ['code' => 0, 'msg' => $response['msg'], 'data' => $response];
    }

    /**
     * 获取部门成员详情
     * @return array
     */
    public function getDepartmentUserList()
    {
        $params = request()->get();
        if ($params['department_id'] === '0') {
            return ['code' => 1, 'msg' => '', 'data' => []];
        }
        $queryarr = array(
            'department_id' => $params['department_id'],
            'offset'        => isset($params['offset']) ? $params['offset'] : 0,
            'page_size'     => isset($params['limit']) ? $params['limit'] : 10,
            'fetch_child'   => false
        );
        $options = array(CURLOPT_HTTPHEADER => [
            'Content-Type:application/json',
            'Authorization:Bearer '.$this->getTenantAccessToken()
        ]);
        $response = Http::get(self::GET_DEPARTMENT_USER_LIST_URL, $queryarr, $options);
        $response = (array) json_decode($response, true);

        if (!$response['code']) {
            $data = [];
            if (isset($response['data']['user_infos'])){
                foreach ($response['data']['user_infos'] as $v) {
                    $data[] = array(
                        'userid'    => $v['employee_id'],
                        'avatar'    => $v['avatar_url'],
                        'name'      => $v['name'],
                        'position'      => $v['work_station'],
                        'mobile'      => isset($v['mobile']) ? $v['mobile'] : '',
                        'email'      => $v['email'],
                        'active'      => $v['status'] === 0 ? true : false
                    );
                }
            }
            return ['code' => 1, 'data' => $data];
        }
        return ['code' => 0, 'msg' => $response['msg'], 'data' => $response];
    }

    /**
     * 获取部门成员人数
     * @return array
     */
    public function getDepartmentUserCount()
    {
        $params = request()->get();
        if ($params['department_id'] === '0') {
            return ['code' => 1, 'msg' => '', 'data' => []];
        }
        $queryarr = array(
            'department_id' => $params['department_id'],
            'offset'        => 0,
            'page_size'     => 100,
            'fetch_child'   => false
        );
        $options = array(CURLOPT_HTTPHEADER => [
            'Content-Type:application/json',
            'Authorization:Bearer '.$this->getTenantAccessToken()
        ]);
        $response = Http::get(self::GET_DEPARTMENT_MEMBER_URL, $queryarr, $options);
        $response = (array) json_decode($response, true);
        if (!$response['code']) {
            $count = 0;
            if (isset($response['data']['user_list'])){
                $count = count($response['data']['user_list']);
            }
            return ['code' => 1, 'data' => $count];
        }
        return ['code' => 0, 'msg' => $response['msg'], 'data' => $response];
    }

    /**
     * 获取部门成员userid列表
     * @return array 成员userid数组
     */
    public function getDepartmentUserIds()
    {
        $params = request()->get();
        $queryarr = array(
            'department_id' => $params['department_id'],
            'offset'        => 0,
            'page_size'     => 100,
            'fetch_child'   => false
        );
        $options = array(CURLOPT_HTTPHEADER => [
            'Content-Type:application/json',
            'Authorization:Bearer '.$this->getTenantAccessToken()
        ]);
        $response = Http::get(self::GET_DEPARTMENT_MEMBER_URL, $queryarr, $options);
        $response = (array) json_decode($response, true);
        if (!$response['code']) {
            $userids = [];
            if (isset($response['data']['user_list'])){
                foreach ($response['data']['user_list'] as $k => $v) {
                    $userids[] = $v['employee_id'];
                }
            }
            return ['code' => 1, 'data' => $userids];
        }
        return ['code' => 0, 'msg' => $response['msg'], 'data' => $response];
    }
}
